package com.youlu.campus.admin.data.service.impl;

import com.youlu.campus.admin.data.entity.*;
import com.youlu.campus.admin.data.service.DayDataStatisticsService;
import com.youlu.campus.admin.utils.DateTimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@Service
public class DayDataStatisticsServiceImpl implements DayDataStatisticsService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public HashMap<String, DayUserStatistics> getDayUserStatisticsOverview(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取日用户数据统计概览,startTime:{},endTime:{}", startTime, endTime);
        if (Objects.isNull(startTime)) {
            startTime = this.getDay0Time();
        }
        if (Objects.isNull(endTime)) {
            endTime = this.getDay23Time(startTime);
        }
        HashMap<String, DayUserStatistics> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(DateTimeUtils.dateToISODate(startTime)), Criteria.where("statisticsTime").lte(DateTimeUtils.dateToISODate(endTime)));
        query.addCriteria(criteria);
        DayUserStatistics dayUserStatistics = mongoTemplate.findOne(query, DayUserStatistics.class);
        if (Objects.nonNull(dayUserStatistics)) {
            result.put("data", dayUserStatistics);
        }
        return result;
    }

    @Override
    public HashMap<String, DayGroupStatistics> getDayGroupStatisticsOverview(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取日用户数据统计概览,startTime:{},endTime:{}", startTime, endTime);
        if (Objects.isNull(startTime)) {
            startTime = this.getDay0Time();
        }
        if (Objects.isNull(endTime)) {
            endTime = this.getDay23Time(startTime);
        }
        HashMap<String, DayGroupStatistics> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        DayGroupStatistics d = mongoTemplate.findOne(query, DayGroupStatistics.class);
        if (Objects.nonNull(d)) {
            result.put("data", d);
        }
        return result;
    }

    @Override
    public HashMap<String, DayCheckInStatistics> getDayCheckInStatisticsOverview(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取日打卡数据统计概览,startTime:{},endTime:{}", startTime, endTime);
        if (Objects.isNull(startTime)) {
            startTime = this.getDay0Time();
        }
        if (Objects.isNull(endTime)) {
            endTime = this.getDay23Time(startTime);
        }
        HashMap<String, DayCheckInStatistics> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        DayCheckInStatistics d = mongoTemplate.findOne(query, DayCheckInStatistics.class);
        if (Objects.nonNull(d)) {
            result.put("data", d);
        }
        return result;
    }

    @Override
    public HashMap<String, DayMemberGroupStatistics> getDayMemberGroupStatisticsOverview(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取日小组数据统计概览,startTime:{},endTime:{}", startTime, endTime);
        if (Objects.isNull(startTime)) {
            startTime = this.getDay0Time();
        }
        if (Objects.isNull(endTime)) {
            endTime = this.getDay23Time(startTime);
        }
        HashMap<String, DayMemberGroupStatistics> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        DayMemberGroupStatistics d = mongoTemplate.findOne(query, DayMemberGroupStatistics.class);
        if (Objects.nonNull(d)) {
            result.put("data", d);
        }
        return result;
    }

    @Override
    public HashMap<String, DayGroupLeaderStatistics> getDayGroupLeaderStatisticsOverview(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取日小组数据统计概览,startTime:{},endTime:{}", startTime, endTime);
        if (Objects.isNull(startTime)) {
            startTime = this.getDay0Time();
        }
        if (Objects.isNull(endTime)) {
            endTime = this.getDay23Time(startTime);
        }
        HashMap<String, DayGroupLeaderStatistics> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        DayGroupLeaderStatistics d = mongoTemplate.findOne(query, DayGroupLeaderStatistics.class);
        if (Objects.nonNull(d)) {
            result.put("data", d);
        }
        return result;
    }

    @Override
    public HashMap<String, DayCommunityStatistic> getDayCommunityStatisticOverview(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取日小组数据统计概览,startTime:{},endTime:{}", startTime, endTime);
        if (Objects.isNull(startTime)) {
            startTime = this.getDay0Time();
        }
        if (Objects.isNull(endTime)) {
            endTime = this.getDay23Time(startTime);
        }
        HashMap<String, DayCommunityStatistic> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        DayCommunityStatistic d = mongoTemplate.findOne(query, DayCommunityStatistic.class);
        if (Objects.nonNull(d)) {
            result.put("data", d);
        }
        return result;
    }

    @Override
    public HashMap<String, List<DayUserStatistics>> getUserStatisticsHistory(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取用户数据统计历史,startTime:{},endTime:{}", startTime, endTime);
        this.setThreeDaysTimes(startTime, endTime);
        HashMap<String, List<DayUserStatistics>> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        List<DayUserStatistics> dayUserStatisticss = mongoTemplate.find(query, DayUserStatistics.class);

        if (CollectionUtils.isEmpty(dayUserStatisticss)) {
            dayUserStatisticss = new ArrayList<>(1);
        }
        result.put("data", dayUserStatisticss);
        return result;
    }

    @Override
    public HashMap<String, List<DayGroupStatistics>> getGroupStatisticsHistory(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取小组数据统计历史,startTime:{},endTime:{}", startTime, endTime);
        this.setThreeDaysTimes(startTime, endTime);
        HashMap<String, List<DayGroupStatistics>> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        List<DayGroupStatistics> datas = mongoTemplate.find(query, DayGroupStatistics.class);

        if (CollectionUtils.isEmpty(datas)) {
            datas = new ArrayList<>(1);
        }
        result.put("data", datas);
        return result;
    }

    @Override
    public HashMap<String, List<DayCheckInStatistics>> getCheckInStatisticsHistory(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取打卡数据统计历史,startTime:{},endTime:{}", startTime, endTime);
        this.setThreeDaysTimes(startTime, endTime);
        HashMap<String, List<DayCheckInStatistics>> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        List<DayCheckInStatistics> datas = mongoTemplate.find(query, DayCheckInStatistics.class);

        if (CollectionUtils.isEmpty(datas)) {
            datas = new ArrayList<>(1);
        }
        result.put("data", datas);
        return result;
    }

    @Override
    public HashMap<String, List<DayMemberGroupStatistics>> getMemberGroupStatisticsHistory(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取小组成员数据统计历史,startTime:{},endTime:{}", startTime, endTime);
        this.setThreeDaysTimes(startTime, endTime);
        HashMap<String, List<DayMemberGroupStatistics>> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        List<DayMemberGroupStatistics> datas = mongoTemplate.find(query, DayMemberGroupStatistics.class);

        if (CollectionUtils.isEmpty(datas)) {
            datas = new ArrayList<>(1);
        }
        result.put("data", datas);
        return result;
    }

    @Override
    public HashMap<String, List<DayGroupLeaderStatistics>> getGroupLeaderStatisticsHistory(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取小组组长数据统计历史,startTime:{},endTime:{}", startTime, endTime);
        this.setThreeDaysTimes(startTime, endTime);
        HashMap<String, List<DayGroupLeaderStatistics>> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        List<DayGroupLeaderStatistics> datas = mongoTemplate.find(query, DayGroupLeaderStatistics.class);

        if (CollectionUtils.isEmpty(datas)) {
            datas = new ArrayList<>(1);
        }
        result.put("data", datas);
        return result;
    }

    @Override
    public HashMap<String, List<DayCommunityStatistic>> getCommunityStatisticHistory(String tenantId, Date startTime, Date endTime) {
        log.info(":>>> 开始获取社区数据统计历史,startTime:{},endTime:{}", startTime, endTime);
        this.setThreeDaysTimes(startTime, endTime);
        HashMap<String, List<DayCommunityStatistic>> result = new HashMap<>();
        Query query = new Query();
        Criteria criteria = new Criteria().andOperator(Criteria.where("statisticsTime").gte(startTime), Criteria.where("statisticsTime").lte(endTime));
        query.addCriteria(criteria);
        List<DayCommunityStatistic> datas = mongoTemplate.find(query, DayCommunityStatistic.class);

        if (CollectionUtils.isEmpty(datas)) {
            datas = new ArrayList<>(1);
        }
        result.put("data", datas);
        return result;
    }

    /**
     * 获取当日零点
     *
     * @return
     */
    private Date getDay0Time() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date d = calendar.getTime();
        return d;
    }

    private Date getDay23Time(Date date) {
        Date d = new Date(date.getTime() + 24 * 60 * 60 * 1000L);
        return d;
    }

    private void setDayTimes(Date startTime, Date endTime) {
        Date d = this.getDay0Time();
        if (Objects.isNull(startTime)) {
            startTime = d;
        }
        if (Objects.isNull(endTime)) {
            endTime = new Date(d.getTime() + 24 * 60 * 60 * 1000L);
        }
        log.info(":.>> startTime:{},endTime:{}", startTime, endTime);
    }

    private void setThreeDaysTimes(Date startTime, Date endTime) {
        Date d = this.getDay0Time();
        if (Objects.isNull(startTime)) {
            startTime = d;
        }
        if (Objects.isNull(endTime)) {
            endTime = new Date(d.getTime() + 3 * 24 * 60 * 60 * 1000L);
        }
    }

}
